package lol.clann.minecraft.springboot.api.bukkit.utils;

import com.ruoshui.utils.java.exception.ExceptionUtils;
import io.netty.channel.Channel;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;

import java.nio.charset.StandardCharsets;
import java.util.UUID;

/**
 *
 * @author pyz
 * @date 2019/5/2 5:27 PM
 */
public interface PlayerUtils {
    /**
     * Bukkit转NMS
     * @param player
     * @param <T>
     * @return
     */
    <T> T toNMS(Player player);

    /**
     * 直接发包
     * @param player
     * @param packet NMS包
     * @param <T>
     */
    <T> void sendPacket(Player player, T packet);

    default boolean isPlayer(Entity entity) {
        return entity instanceof Player;
    }

    default void printException(Player player, Throwable e) {
        if (e == null) {
            return;
        }
        e = ExceptionUtils.unwrap(e);
        player.sendMessage(ChatColor.RED + e.getMessage());
        for (StackTraceElement stackTraceElement : e.getStackTrace()) {
            player.sendMessage(ChatColor.RED + stackTraceElement.getClassName() + stackTraceElement.getMethodName() + ":" + stackTraceElement.getLineNumber());
        }
    }

    /**
     * NMS转Bukkit
     *
     * @param nmsPlayer
     * @param <T>
     * @return
     */
    <T> Player toBukkit(T nmsPlayer);

    public <T> T getNetworkManager(Player player);

    public <T> T getPlayerConnection(Player player);

    Channel getChannel(Player player);

    public void sendPluginMessage(Player player, String channel, byte[] message);

    default public void sendPluginMessage(Player player, Plugin plugin, String channel, byte[] message) {
        player.sendPluginMessage(plugin, channel, message);
    }

    /**
     * 计算离线UUID
     *
     * @param playerName
     * @return
     */
    default public UUID getOfflineUUID(String playerName) {
        return UUID.nameUUIDFromBytes(("OfflinePlayer:" + playerName).getBytes(StandardCharsets.UTF_8));
    }

    default public void updateHeldItemSlot(Player p) {
        p.getInventory().setHeldItemSlot(p.getInventory().getHeldItemSlot());
    }

    /**
     * 因为某些原因,客户端和服务端玩家快捷栏位置可能不一样
     * 此方法能同步客户端的快捷栏位置
     *
     * @param player
     */
    public void refreshHotbarIndex(Player player);

    /**
     * 获取玩家的客户端IP
     * @param p
     * @return
     */
    default public String getPlayerIp(Player p) {
        return p.getAddress().getHostString().replaceFirst("/", "");
    }

    /**
     * 获取玩家的服务端产IP(如果是多线服,可用此方法判断玩家使用的是哪个IP)
     * @param p
     * @return
     */
    default public String getServerIp(Player p) {
        Channel channel = getChannel(p);
        return channel.localAddress().toString().replaceFirst("/", "").split(":", 2)[0];
    }

    /**
     * 将OfflinePlayer转换成Player对象. 方便读取背包
     * @param p
     * @return
     */
    Player toOnlinePlayer(OfflinePlayer p);

    default public Player getOnlinePlayer(String name) {
        Player p = Bukkit.getServer().getPlayer(name);
        if (p == null || !p.getName().equals(name)) {
            return null;
        }
        return p;
    }

    default public OfflinePlayer getOfflinePlayer(String name) {
        OfflinePlayer p = Bukkit.getServer().getOfflinePlayer(name);
        if (p == null || !p.getName().equals(name)) {
            return null;
        }
        return p;
    }

    default public void toggleFly(Player p, boolean b) {
        p.setFallDistance(0.0F);
        if (b) {
            p.setAllowFlight(true);
        } else {
            p.setAllowFlight(false);
            p.setFlying(b);
        }
    }

    default public void closeScreen(Player p) {
        p.closeInventory();
    }

    /**
     * 发送Title
     * 1.8+
     *
     * @param player
     * @param title
     * @param subtitle
     * @param fadeIn
     * @param stay
     * @param fadeOut
     */
    void sendTitle(Player player, String title, String subtitle, int fadeIn, int stay, int fadeOut);
}
